import os
import shutil
import tkinter as tk
import zipfile
from datetime import datetime
from tkinter import filedialog
from tkinter import ttk, messagebox

import patoolib

from models.task_models import Task, TaskStatus, TaskPriority
from notify.notification_setting_dialog import NotificationSettingsDialog
from utils.file_util import FileUtil


class TaskManagerView:
    """任务管理界面 - 支持独立窗口和内嵌模式"""

    def __init__(self, parent, db, notification_system, container=None):
        """
        初始化任务管理器
        :param parent: 父窗口（用于独立模式）
        :param db: 数据库实例
        :param notification_system: 通知系统实例
        :param container: 内嵌模式的容器（可选）
        """
        self.db = db
        self.current_task = None
        self.notification_system = notification_system
        self.container = container
        self.total_pages = 1
        self.search_var = None
        self.status_filter_var = None
        self.date_filter_var = None
        self.task_tree = None
        self.page_var = None
        self.per_page = None
        self.page_entry = None
        self.title_var = None
        self.due_date_var = None
        self.interval_var = None
        self.priority_var = None
        self.status_var = None
        self.reminder_status_var = None
        self.reminder_status_label = None
        self.description_text = None
        self.attachment_list = None

        # 根据是否提供容器决定使用独立窗口还是内嵌模式
        if container:
            # 内嵌模式
            self.frame = ttk.Frame(container)
            self.frame.pack(fill=tk.BOTH, expand=True)
            self.create_widgets(self.frame)
        else:
            # 独立窗口模式
            self.top = tk.Toplevel(parent)
            self.top.title("任务管理")
            self.top.geometry("1000x750")
            self.top.transient(parent)
            self.top.grab_set()
            self.top.resizable(True, True)
            self.frame = self.top
            self.create_widgets(self.top)

    def create_widgets(self, parent):
        """创建界面控件"""
        # 创建主框架
        main_frame = ttk.Frame(parent, padding=15)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 标题和按钮区域
        header_frame = ttk.Frame(main_frame)
        header_frame.pack(fill=tk.X, pady=(0, 15))

        ttk.Label(
            header_frame,
            text="任务管理系统",
            font=("Arial", 16, "bold")
        ).pack(side=tk.LEFT)

        # 独立窗口模式显示关闭按钮
        if not self.container:
            ttk.Button(
                header_frame,
                text="关闭",
                command=self.close_window,
                width=10
            ).pack(side=tk.RIGHT, padx=5)

        ttk.Button(
            header_frame,
            text="通知设置",
            command=self.open_notification_settings,
            width=10
        ).pack(side=tk.RIGHT, padx=5)

        ttk.Button(
            header_frame,
            text="+ 新建任务",
            command=self.create_new_task,
            width=15
        ).pack(side=tk.RIGHT, padx=5)

        # 任务列表和详情区域
        content_frame = ttk.Frame(main_frame)
        content_frame.pack(fill=tk.BOTH, expand=True)

        # 任务列表
        list_frame = ttk.LabelFrame(content_frame, text="任务列表")
        list_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))

        # 搜索框
        search_frame = ttk.Frame(list_frame)
        search_frame.pack(fill=tk.X, pady=(0, 10))

        self.search_var = tk.StringVar()
        ttk.Entry(
            search_frame,
            textvariable=self.search_var,
            width=30
        ).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))

        ttk.Button(
            search_frame,
            text="搜索",
            command=self.search_tasks,
            width=8
        ).pack(side=tk.RIGHT)
        # 筛选区域
        filter_frame = ttk.Frame(list_frame)
        filter_frame.pack(fill=tk.X, pady=(0, 10))

        # 状态筛选
        ttk.Label(filter_frame, text="状态:").pack(side=tk.LEFT, padx=(0, 5))
        self.status_filter_var = tk.StringVar(value="未完成")
        status_filter_combo = ttk.Combobox(
            filter_frame,
            textvariable=self.status_filter_var,
            values=["全部", "未完成", "已完成", "待处理", "进行中", "已过期"],
            state="readonly",
            width=10
        )
        status_filter_combo.pack(side=tk.LEFT, padx=(0, 10))

        # 截止日期筛选
        ttk.Label(filter_frame, text="截止日期:").pack(side=tk.LEFT, padx=(0, 5))
        self.date_filter_var = tk.StringVar(value="三天内")
        date_filter_combo = ttk.Combobox(
            filter_frame,
            textvariable=self.date_filter_var,
            values=["全部", "今天", "三天内", "一周内", "一个月内", "自定义"],
            state="readonly",
            width=10
        )
        date_filter_combo.pack(side=tk.LEFT, padx=(0, 10))

        # 应用筛选按钮
        ttk.Button(
            filter_frame,
            text="应用筛选",
            command=self.apply_filters,
            width=10
        ).pack(side=tk.RIGHT)

        # 任务表格
        self.task_tree = ttk.Treeview(
            list_frame,
            columns=("id", "title", "due_date", "days_left", "priority", "status"),
            show="headings",
            height=15
        )

        # 设置列
        self.task_tree.heading("id", text="ID")
        self.task_tree.heading("title", text="任务标题")
        self.task_tree.heading("due_date", text="截止日期")
        self.task_tree.heading("days_left", text="到期时间")
        self.task_tree.heading("priority", text="优先级")
        self.task_tree.heading("status", text="状态")

        # 设置列宽
        self.task_tree.column("id", width=50, anchor=tk.CENTER)
        self.task_tree.column("title", width=180)
        self.task_tree.column("due_date", width=90, anchor=tk.CENTER)
        self.task_tree.column("days_left", width=80, anchor=tk.CENTER)
        self.task_tree.column("priority", width=70, anchor=tk.CENTER)
        self.task_tree.column("status", width=70, anchor=tk.CENTER)

        # 配置颜色标签
        self.task_tree.tag_configure('urgent', foreground='red')
        self.task_tree.tag_configure('warning', foreground='orange')
        self.task_tree.tag_configure('normal', foreground='green')
        self.task_tree.tag_configure('expired', foreground='gray')

        self.task_tree.pack(fill=tk.BOTH, expand=True)
        self.task_tree.bind("<<TreeviewSelect>>", self.on_task_select)

        # 分页控件
        pagination_frame = ttk.Frame(list_frame)
        pagination_frame.pack(fill=tk.X, pady=(5, 0))

        self.page_var = tk.IntVar(value=1)
        self.total_pages = 1
        self.per_page = 10  # 每页显示的任务数量

        ttk.Button(
            pagination_frame,
            text="上一页",
            command=lambda: self.change_page(-1),
            width=8
        ).pack(side=tk.LEFT)

        ttk.Label(
            pagination_frame,
            textvariable=tk.StringVar(value="页码:")
        ).pack(side=tk.LEFT, padx=(10, 0))

        self.page_entry = ttk.Entry(
            pagination_frame,
            textvariable=self.page_var,
            width=4
        )
        self.page_entry.pack(side=tk.LEFT)
        self.page_entry.bind("<Return>", lambda e: self.load_tasks())

        ttk.Label(
            pagination_frame,
            textvariable=tk.StringVar(value=f"/ {self.total_pages}")
        ).pack(side=tk.LEFT)

        ttk.Button(
            pagination_frame,
            text="下一页",
            command=lambda: self.change_page(1),
            width=8
        ).pack(side=tk.LEFT, padx=(5, 0))

        ttk.Label(
            pagination_frame,
            text=f"每页: {self.per_page} 条"
        ).pack(side=tk.RIGHT)

        # 任务详情
        detail_frame = ttk.LabelFrame(content_frame, text="任务详情")
        detail_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 表单区域
        form_frame = ttk.Frame(detail_frame)
        form_frame.pack(fill=tk.X, pady=10)

        # 任务标题
        ttk.Label(form_frame, text="任务标题:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        self.title_var = tk.StringVar()
        ttk.Entry(form_frame, textvariable=self.title_var, width=40).grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)

        # 截止日期
        ttk.Label(form_frame, text="截止日期:").grid(row=1, column=0, sticky=tk.W, padx=5, pady=5)
        self.due_date_var = tk.StringVar()
        ttk.Entry(form_frame, textvariable=self.due_date_var, width=20).grid(row=1, column=1, sticky=tk.W, padx=5,
                                                                             pady=5)
        ttk.Button(
            form_frame,
            text="选择日期",
            command=self.select_date,
            width=10
        ).grid(row=1, column=2, padx=5, pady=5)

        # 提醒间隔
        ttk.Label(form_frame, text="提醒间隔(天):").grid(row=2, column=0, sticky=tk.W, padx=5, pady=5)
        self.interval_var = tk.IntVar(value=1)
        ttk.Spinbox(
            form_frame,
            from_=1,
            to=7,
            textvariable=self.interval_var,
            width=5
        ).grid(row=2, column=1, sticky=tk.W, padx=5, pady=5)

        # 优先级
        ttk.Label(form_frame, text="优先级:").grid(row=3, column=0, sticky=tk.W, padx=5, pady=5)
        self.priority_var = tk.StringVar(value=TaskPriority.MEDIUM.value)
        ttk.Combobox(
            form_frame,
            textvariable=self.priority_var,
            values=[p.value for p in TaskPriority],
            state="readonly",
            width=10
        ).grid(row=3, column=1, sticky=tk.W, padx=5, pady=5)

        # 状态
        ttk.Label(form_frame, text="状态:").grid(row=4, column=0, sticky=tk.W, padx=5, pady=5)
        self.status_var = tk.StringVar(value=TaskStatus.PENDING.value)
        ttk.Combobox(
            form_frame,
            textvariable=self.status_var,
            values=[s.value for s in TaskStatus],
            state="readonly",
            width=10
        ).grid(row=4, column=1, sticky=tk.W, padx=5, pady=5)

        ttk.Label(form_frame, text="提醒状态:").grid(row=5, column=0, sticky=tk.W, padx=5, pady=5)
        self.reminder_status_var = tk.StringVar(value="未提醒")
        self.reminder_status_label = ttk.Label(form_frame, textvariable=self.reminder_status_var,
                                               foreground="red", font=("Arial", 9))
        self.reminder_status_label.grid(
            row=5, column=1, sticky=tk.W, padx=5, pady=5)

        # 任务描述
        ttk.Label(detail_frame, text="任务描述:").pack(anchor=tk.W, padx=5, pady=(10, 0))
        self.description_text = tk.Text(detail_frame, height=8)
        self.description_text.pack(fill=tk.X, padx=5, pady=5)

        # 附件区域
        attachment_frame = ttk.LabelFrame(detail_frame, text="附件")
        attachment_frame.pack(fill=tk.X, padx=5, pady=10)

        self.attachment_list = tk.Listbox(attachment_frame, height=4, selectmode="browse")
        self.attachment_list.pack(fill=tk.X, padx=5, pady=5)

        btn_frame = ttk.Frame(attachment_frame)
        btn_frame.pack(fill=tk.X, padx=5, pady=(0, 5))

        ttk.Button(
            btn_frame,
            text="打开附件",
            command=self.open_attachment,
            width=10
        ).pack(side=tk.LEFT)

        ttk.Button(
            btn_frame,
            text="添加附件",
            command=self.add_attachment,
            width=10
        ).pack(side=tk.LEFT, padx=(0, 5))

        ttk.Button(
            btn_frame,
            text="删除附件",
            command=self.remove_attachment,
            width=10
        ).pack(side=tk.LEFT)

        # 操作按钮
        action_frame = ttk.Frame(detail_frame)
        action_frame.pack(fill=tk.X, pady=10)

        ttk.Button(
            action_frame,
            text="立即提醒",
            command=self.trigger_reminder,
            width=15
        ).pack(side=tk.RIGHT, padx=5)

        ttk.Button(
            action_frame,
            text="保存任务",
            command=self.save_task,
            style="Accent.TButton",
            width=15
        ).pack(side=tk.RIGHT, padx=5)

        ttk.Button(
            action_frame,
            text="删除任务",
            command=self.delete_task,
            width=15
        ).pack(side=tk.RIGHT, padx=5)

        # 加载任务列表
        self.load_tasks()

    def close_window(self):
        """关闭独立窗口"""
        if hasattr(self, 'top'):
            self.top.destroy()

    def apply_filters(self):
        """应用筛选条件"""
        self.page_var.set(1)  # 重置到第一页
        self.load_tasks()

    def change_page(self, delta):
        """切换页面"""
        current_page = self.page_var.get()
        new_page = current_page + delta

        if 1 <= new_page <= self.total_pages:
            self.page_var.set(new_page)
            self.load_tasks()

    def load_tasks(self):
        """加载任务列表（带筛选和分页）"""
        # 获取筛选条件
        status_filter = self.status_filter_var.get()
        date_filter = self.date_filter_var.get()
        # 转换筛选条件
        status_mapping = {
            "全部": None,
            "未完成": "uncompleted",
            "已完成": TaskStatus.COMPLETED.value,
            "待处理": TaskStatus.PENDING.value,
            "已过期": TaskStatus.EXPIRED.value
        }
        # 获取任务数据（带分页）
        page = self.page_var.get()
        tasks, total_count = self.db.get_tasks_with_filter(
            status=status_mapping.get(status_filter),
            date_filter=date_filter,
            page=page,
            per_page=self.per_page
        )

        # 计算总页数
        self.total_pages = max(1, (total_count + self.per_page - 1) // self.per_page)
        self.page_var.set(min(page, self.total_pages))  # 确保页码在有效范围内

        # 清空当前任务列表
        self.task_tree.delete(*self.task_tree.get_children())
        # 添加任务到列表
        today = datetime.now().date()
        for task in tasks:
            due_date = task.due_date
            days_left = (due_date - today).days

            # 确定标签（颜色）
            tag = 'normal'
            if days_left < 0:
                tag = 'expired'
            elif days_left == 0:
                tag = 'urgent'
            elif days_left <= 2:
                tag = 'warning'

            # 格式化剩余时间显示
            days_left_str = f"{days_left}天" if days_left > 0 else "已过期"
            if days_left == 0:
                days_left_str = "今天"

            # 插入任务行
            self.task_tree.insert("", "end", values=(
                task.id,
                task.title,
                due_date.strftime("%Y-%m-%d"),
                days_left_str,  # 显示剩余时间
                task.priority.value,
                task.status.value
            ), tags=(tag,))

    def search_tasks(self):
        """搜索任务"""
        keyword = self.search_var.get().strip()
        if not keyword:
            self.load_tasks()
            return

        self.task_tree.delete(*self.task_tree.get_children())
        tasks = self.db.get_all_tasks()
        for task in tasks:
            if (keyword.lower() in task.title.lower() or
                    keyword.lower() in task.description.lower()):
                self.task_tree.insert("", "end", values=(
                    task.id,
                    task.title,
                    task.due_date.strftime("%Y-%m-%d"),
                    task.priority.value,
                    task.status.value
                ))

    def on_task_select(self, event):
        """任务选择事件"""
        selected = self.task_tree.selection()
        if not selected:
            return

        item = self.task_tree.item(selected[0])
        task_id = item["values"][0]
        task = self.db.get_task(task_id)
        self.current_task = task
        self.display_task(task)

    def display_task(self, task):
        """显示任务详情"""
        self.title_var.set(task.title)
        self.due_date_var.set(task.due_date.strftime("%Y-%m-%d"))
        self.interval_var.set(task.interval_days)
        self.priority_var.set(task.priority.value)
        self.status_var.set(task.status.value)

        self.description_text.delete(1.0, tk.END)
        self.description_text.insert(tk.END, task.description)

        self.attachment_list.delete(0, tk.END)
        for attachment in task.attachments:
            self.attachment_list.insert(tk.END, attachment)
        self.update_reminder_status(task)

    def update_reminder_status(self, task=None):
        """更新提醒状态显示"""
        if not task and self.current_task:
            task = self.current_task

        if task:
            if task.is_reminded:
                status = f"已提醒 ({task.last_reminded.strftime('%Y-%m-%d %H:%M')})"
                color = "green"
            else:
                status = "未提醒"
                color = "red"

            self.reminder_status_var.set(status)
            self.reminder_status_label.configure(foreground=color)

    def trigger_reminder(self):
        """触发立即提醒"""
        if not self.current_task:
            messagebox.showwarning("提醒失败", "请先选择一个任务")
            return

        self.notification_system.show_notification(task=self.current_task)

    def create_new_task(self):
        """创建新任务"""
        self.current_task = None
        self.title_var.set("")
        self.due_date_var.set("")
        self.interval_var.set(1)
        self.priority_var.set(TaskPriority.MEDIUM.value)
        self.status_var.set(TaskStatus.PENDING.value)
        self.description_text.delete(1.0, tk.END)
        self.attachment_list.delete(0, tk.END)

    def select_date(self):
        """选择日期"""
        from tkcalendar import Calendar

        top = tk.Toplevel(self.frame)
        top.title("选择日期")
        top.transient(self.frame)
        top.grab_set()

        cal = Calendar(top, selectmode="day", date_pattern="yyyy-mm-dd")
        cal.pack(padx=10, pady=10)

        ttk.Button(
            top,
            text="确定",
            command=lambda: self.set_date(cal.get_date(), top)
        ).pack(pady=5)

    def set_date(self, date_str, window):
        """设置日期"""
        self.due_date_var.set(date_str)
        window.destroy()

    def open_attachment(self):
        if self.attachment_list.size() > 0:
            FileUtil.open_file_directory(self.attachment_list.get(0))
        else:
            messagebox.showwarning("警告", "请先选择文件目录")

    def add_attachment(self):
        """添加附件（仅文件夹或压缩包，自动解压，限制一个）"""
        file_path = filedialog.askopenfilename(
            title="选择文件夹或压缩包",
            filetypes=[
                ("压缩文件", "*.zip *.rar *.7z"),
                ("所有文件", "*.*")
            ]
        )
        if not file_path:
            return

        # 清空当前附件（限制只允许一个）
        self.attachment_list.delete(0, tk.END)

        if os.path.isdir(file_path):
            # 直接选择了一个文件夹
            self.attachment_list.insert(tk.END, file_path)
        else:
            ext = os.path.splitext(file_path)[1].lower()
            filename = os.path.basename(file_path)
            folder_name = os.path.splitext(filename)[0]
            target_dir = os.path.join(os.path.dirname(file_path), folder_name)

            if os.path.exists(target_dir):
                if messagebox.askyesno("覆盖确认", f"目录 {folder_name} 已存在，是否覆盖？"):
                    shutil.rmtree(target_dir)
                else:
                    return

            try:
                os.makedirs(target_dir, exist_ok=True)
                if ext == ".zip":
                    with zipfile.ZipFile(file_path, 'r') as zip_ref:
                        zip_ref.extractall(target_dir)
                elif ext in [".rar", ".7z"]:
                    patoolib.extract_archive(file_path, outdir=target_dir)
                else:
                    messagebox.showerror("错误", "请选择文件夹或支持的压缩包 (.zip/.rar/.7z)")
                    return
            except Exception as e:
                messagebox.showerror("解压失败", f"解压失败: {str(e)}")
                return

            self.attachment_list.insert(tk.END, target_dir)

    def remove_attachment(self):
        """删除附件"""
        selected = self.attachment_list.curselection()
        if selected:
            self.attachment_list.delete(selected[0])

    def save_task(self):
        """保存任务"""
        # 验证输入
        if not self.title_var.get().strip():
            messagebox.showerror("错误", "任务标题不能为空")
            return

        try:
            due_date = datetime.strptime(self.due_date_var.get(), "%Y-%m-%d").date()
        except ValueError:
            messagebox.showerror("错误", "日期格式不正确，请使用YYYY-MM-DD格式")
            return

        # 创建或更新任务
        if self.current_task:
            task = self.current_task
        else:
            task = Task(
                title=self.title_var.get().strip(),
                description=self.description_text.get(1.0, tk.END).strip(),
                due_date=due_date,
                interval_days=self.interval_var.get(),
                priority=TaskPriority(self.priority_var.get())
            )

        task.title = self.title_var.get().strip()
        task.description = self.description_text.get(1.0, tk.END).strip()
        task.due_date = due_date
        task.interval_days = self.interval_var.get()
        task.priority = TaskPriority(self.priority_var.get())
        task.status = TaskStatus(self.status_var.get())

        # 获取附件列表
        attachments = [self.attachment_list.get(i) for i in range(self.attachment_list.size())]
        task.attachments = attachments

        # 保存到数据库
        if self.current_task:
            self.db.update_task(task)
        else:
            self.db.add_task(task)

        messagebox.showinfo("成功", "任务已保存")
        self.load_tasks()
        self.current_task = task

    def delete_task(self):
        """删除任务"""
        if not self.current_task:
            messagebox.showerror("错误", "请先选择一个任务")
            return

        if messagebox.askyesno("确认", "确定要删除这个任务吗？"):
            self.db.delete_task(self.current_task.id)
            self.load_tasks()
            self.create_new_task()
            messagebox.showinfo("成功", "任务已删除")

    def open_notification_settings(self):
        """打开通知设置窗口"""
        NotificationSettingsDialog(self.frame, self.db)
